package com.yfbao.horizon.schedule.tk.front.service;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 前端日志监控服务
 */
@Component
public class SeeyonFrontMonitor implements MeterBinder {
    // 队列指标
    private final AtomicInteger currentQueueSize = new AtomicInteger();
    private final int queueCapacity = 10_000; // 与FrontendLogService中的QUEUE_CAPACITY保持一致

    // 计数器
    private Counter logsReceivedAccepted;
    private Counter logsReceivedRejected;
    private Counter logsProcessedTotal;
    private Counter errorsTotal;

    // 计时器
    private Timer processingTimer;
    private Timer queueTimer;

    // 摘要
    private final Summary batchSize = new Summary();

    @Override
    public void bindTo(MeterRegistry registry) {
        // 初始化队列指标
        Gauge.builder("frontend.log.queue.size", currentQueueSize, AtomicInteger::get)
                .description("Current number of logs in the queue")
                .register(registry);

        Gauge.builder("frontend.log.queue.capacity", () -> queueCapacity)
                .description("Maximum capacity of the queue")
                .register(registry);

        Gauge.builder("frontend.log.queue.usage.ratio",
                        () -> queueCapacity > 0 ? (double) currentQueueSize.get() / queueCapacity : 0)
                .description("Queue usage ratio (current_size / capacity)")
                .register(registry);

        // 初始化计数器
        logsReceivedAccepted = Counter.builder("frontend.logs.received")
                .tag("status", "accepted")
                .description("Number of logs accepted into the queue")
                .register(registry);

        logsReceivedRejected = Counter.builder("frontend.logs.received")
                .tag("status", "rejected")
                .description("Number of logs rejected due to full queue")
                .register(registry);

        logsProcessedTotal = Counter.builder("frontend.logs.processed")
                .description("Total number of logs processed")
                .register(registry);

        errorsTotal = Counter.builder("frontend.logs.errors")
                .description("Number of errors during log processing")
                .register(registry);

        // 初始化计时器
        processingTimer = Timer.builder("frontend.log.processing.time")
                .description("Time taken to process logs")
                .publishPercentiles(0.5, 0.95, 0.99)
                .register(registry);

        queueTimer = Timer.builder("frontend.log.queue.time")
                .description("Time logs spend in queue")
                .publishPercentiles(0.5, 0.95, 0.99)
                .register(registry);

        // 初始化摘要
        registry.gauge("frontend.log.batch.size", batchSize, s -> s.getCount() > 0 ? s.getSum() / s.getCount() : 0);
    }

    // 更新队列指标
    public void updateQueueMetrics(int currentSize, int capacity) {
        currentQueueSize.set(currentSize);
    }

    // 记录接收到的日志
    public void incrementLogsReceived(boolean accepted) {
        if (accepted) {
            logsReceivedAccepted.increment();
        } else {
            logsReceivedRejected.increment();
        }
    }

    // 记录已处理的日志
    public void incrementLogsProcessed(int count) {
        logsProcessedTotal.increment(count);
    }

    // 记录批处理大小
    public void recordBatchSize(int size) {
        batchSize.record(size);
    }

    // 记录处理时间
    public void recordProcessingTime(long durationNanos) {
        processingTimer.record(durationNanos, TimeUnit.NANOSECONDS);
    }

    // 记录队列时间
    public void recordQueueTime(long durationNanos) {
        queueTimer.record(durationNanos, TimeUnit.NANOSECONDS);
    }

    // 记录错误
    public void incrementError(String type) {
        errorsTotal.increment();
    }

    // 简单的摘要实现
    private static class Summary {
        private long count;
        private double sum;

        public synchronized void record(double value) {
            count++;
            sum += value;
        }

        public synchronized long getCount() {
            return count;
        }

        public synchronized double getSum() {
            return sum;
        }
    }
}